package com.tobeface.wechat.message;

import com.google.common.collect.Maps;
import com.tobeface.modules.lang.Ghost;
import com.tobeface.modules.lang.Requires;
import com.tobeface.wechat.message.builder.*;

import java.nio.charset.Charset;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author loudyn
 */
public final class WeChatMessageBuilder {
    Map<String, Object> payloads = Maps.newHashMap();
    WeChatMessageVerb verb = WeChatMessageVerb.IGNORE;

    /**
     * @param sender
     * @return
     */
    public WeChatMessageBuilder from(String sender) {
        payload(WeChatMessagePayloads.SENDER_PAYLOAD, sender);
        return this;
    }

    /**
     * @param to
     * @return
     */
    public WeChatMessageBuilder to(String to) {
        payload(WeChatMessagePayloads.RECEIVER_PAYLOAD, to);
        return this;
    }

    /**
     * @param createTime
     * @return
     */
    public WeChatMessageBuilder on(String createTime) {
        payload(WeChatMessagePayloads.CREATETIME_PAYLOAD, createTime);
        return this;
    }

    /**
     * @param verb
     * @return
     */
    public WeChatMessageBuilder verb(String verb) {
        return verb(WeChatMessageVerb.valueOf(verb));
    }

    /**
     * @param verb
     * @return
     */
    public WeChatMessageBuilder verb(WeChatMessageVerb verb) {
        this.verb = verb;
        return this;
    }

    /**
     * @param name
     * @param val
     * @return
     */
    public WeChatMessageBuilder payload(String name, String val) {
        this.payloads.put(name, val);
        return this;
    }

    /**
     * @param payloads
     * @return
     */
    public WeChatMessageBuilder payloads(Map<String, Object> payloads) {
        this.payloads.putAll(payloads);
        return this;
    }

    /**
     * @return
     */
    TextTypedMessageBuilder text() {
        return new TextTypedMessageBuilder(this);
    }

    ImageTypedMessageBuilder image() {
        return new ImageTypedMessageBuilder(this);
    }

    VoiceTypedMessageBuilder voice() {
        return new VoiceTypedMessageBuilder(this);
    }

    VideoTypedMessageBuilder video() {
        return new VideoTypedMessageBuilder(this);
    }

    MusicTypedMessageBuilder music() {
        return new MusicTypedMessageBuilder(this);
    }

    NewsTypedMessageBuilder news() {
        return new NewsTypedMessageBuilder(this);
    }

    /**
     * @param payload
     * @param <T>
     * @return
     */
    public <T extends TypedWeChatMessageBuilder> T payload(Class<T> payload) {
        Ghost<T> ghost = Ghost.me(payload);
        return ghost.born(this);
    }

    /**
     * @return
     */
    public WeChatMessage build() {
        return new WeChatMessage(this);
    }

    /**
     * @param xml
     * @return
     */
    public static WeChatMessageBuilder loads(String xml) {
        Requires.notNull(xml, "xml must not be null!");
        return loads(xml.getBytes(Charset.forName("UTF-8")));
    }

    /**
     * @param content
     * @return
     */
    public static WeChatMessageBuilder loads(byte[] content) {
        Map<String, Object> payloads = WeChatMessagePayloadHelper.loads(content);
        return of().payloads(payloads);
    }

    /**
     * @param sender
     * @param receiver
     * @param createTime
     * @return
     */
    public static WeChatMessageBuilder of() {
        return new WeChatMessageBuilder();
    }

    /**
     * @param message
     * @return
     */
    public static WeChatMessageBuilder reply(WeChatMessage message) {
        Requires.notNull(message, "message must not be null!");
        long nowSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
        return WeChatMessageBuilder.of().from(message.getReceiver())
                                        .to(message.getSender())
                                        .on(String.valueOf(nowSeconds));
    }

    public static <T extends TypedWeChatMessageBuilder> T reply(Class<T> builder) {
        Requires.notNull(builder, "builder must not be null!");
        Ghost<T> ghost = Ghost.me(builder);
        return ghost.born();
    }

    /**
     * @param message
     * @return
     */
    public static TextTypedMessageBuilder replyText(WeChatMessage message) {
        Requires.notNull(message, "message must not be null!");
        return reply(message).text();
    }

    /**
     * @param message
     * @return
     */
    public static ImageTypedMessageBuilder replyImage(WeChatMessage message) {
        Requires.notNull(message, "message must not be null!");
        return reply(message).image();
    }

    /**
     * @param message
     * @return
     */
    public static NewsTypedMessageBuilder replyNews(WeChatMessage message) {
        Requires.notNull(message, "message must not be null!");
        return reply(message).news();
    }

    /**
     * @param message
     * @return
     */
    public static MusicTypedMessageBuilder replyMusic(WeChatMessage message) {
        Requires.notNull(message, "message must not be null!");
        return reply(message).music();
    }

    /**
     * @param message
     * @return
     */
    public static VoiceTypedMessageBuilder replyVoice(WeChatMessage message) {
        Requires.notNull(message, "message must not be null!");
        return reply(message).voice();
    }

    /**
     * @param message
     * @return
     */
    public static VideoTypedMessageBuilder replyVideo(WeChatMessage message) {
        Requires.notNull(message, "message must not be null!");
        return reply(message).video();
    }
}
